home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / gcc / ixemlsrc.lha / ixemul / library / malloc.c < prev    next >
C/C++ Source or Header  |  1996-03-13  |  7KB  |  269 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  malloc.c,v 1.1.1.1 1994/04/04 04:30:29 amiga Exp
  20.  *
  21.  *  malloc.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:30:29  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.5  1992/10/20  16:26:17  mwild
  26.  *  change to single indirection to memory management list, allowing us
  27.  *  to switch lists on the fly (important for vfork).
  28.  *
  29.  *  Revision 1.4  1992/09/14  01:44:41  mwild
  30.  *  reduce magic cookie information by one long. By this, gcc's obstack will
  31.  *  allocate in neat 4k blocks, which makes GigaMem happy (GigaMem is a commercial
  32.  *  VMem package for AmigaDOS).
  33.  *
  34.  *  Revision 1.3  1992/08/09  20:58:57  amiga
  35.  *  add cast
  36.  *
  37.  *  Revision 1.2  1992/05/22  01:43:07  mwild
  38.  *  use buddy-alloc memory management
  39.  *
  40.  * Revision 1.1  1992/05/14  19:55:40  mwild
  41.  * Initial revision
  42.  *
  43.  */
  44.  
  45. #define KERNEL
  46. #include "ixemul.h"
  47. #include "kprintf.h"
  48.  
  49. #include <stddef.h>
  50.  
  51. #define mem_list (u.u_mdp->md_list)
  52. #define mem_used (u.u_mdp->md_malloc_sbrk_used)
  53. #define own_mem_list (u.u_md.md_list)
  54. #define own_mem_used (u.u_md.md_malloc_sbrk_used)
  55.  
  56. #define MAGIC1 0x55555555
  57. #define MAGIC2 0xaaaaaaaa
  58.  
  59. /* use only one magic cookie at the end, since then the most frequently
  60.    done allocation of gcc, 4072 byte, fits neatly into 4096 when we've added
  61.    our information. Gigamem will thank you that it doesn't have to give
  62.    you an additional page for 4 byte ;-)) */
  63.  
  64. struct mem_block {
  65.   struct mem_block *next, *prev;
  66.   u_int           size;
  67.   u_int           magic[2];
  68.   u_int           realblock[1];
  69.   /* realblock should really be [0], and at the end we'd have a magic2[1] */
  70. };
  71.  
  72. struct memalign_ptr {
  73.   u_char    magic;
  74.   u_int        alignment:24;
  75. };
  76.  
  77. #define MEMALIGN_MAGIC 0xdd
  78.  
  79. /* perhaps important later ;-) */
  80. #define PAGESIZE 2048
  81.  
  82. void *
  83. malloc (size_t size)
  84. {
  85.   struct mem_block *res;
  86.  
  87.   /* guarantee long sizes (so we can use CopyMemQuick in realloc) */
  88.   size = (size + 3) & ~3; /* next highest multiple of 4 */
  89.   
  90.   /* include management information */
  91.   res = (struct mem_block *) b_alloc(size + sizeof (struct mem_block), 0); /* not MEMF_PUBLIC ! */
  92.   
  93.   if (res)
  94.     {
  95.       u_int *lp = &res->size;
  96.       *lp++ = size;
  97.       *lp++ = MAGIC1; *lp++ = MAGIC1;
  98.       lp = (u_int *)((u_char *)lp + size);
  99.       *lp++ = MAGIC2; 
  100.       
  101.       Forbid ();
  102.       AddTail ((struct List *) &mem_list, (struct Node *) res);
  103.       Permit ();
  104.  
  105.       mem_used += size;
  106.       return &res->realblock;
  107.     }
  108.   return 0;
  109. }
  110.  
  111. void *
  112. memalign (size_t alignment, size_t size)
  113. {
  114.   u_char *p = (u_char *) malloc (size + alignment + sizeof (struct memalign_ptr));
  115.   struct memalign_ptr *al_start;
  116.  
  117.   if (! p)
  118.     return p;
  119.  
  120.   /* if the block is already aligned right, just return it */
  121.   if (! ((u_int)p & (alignment - 1)))
  122.     return p;
  123.  
  124.   /* else find the start of the aligned block in our larger block */
  125.   al_start = (struct memalign_ptr *)(((u_int)p + alignment - 1) & -alignment);
  126.  
  127.   /* this could be problematic on 68000, when an odd alignment is requested,
  128.    * should I just don't allow odd alignments?? */
  129.   al_start[-1].magic = MEMALIGN_MAGIC;
  130.   al_start[-1].alignment = (u_char *)al_start - p;
  131.  
  132.   return al_start;
  133. }
  134.  
  135. void *
  136. valloc (size_t size)
  137. {
  138.   return (void *) memalign (PAGESIZE, size);
  139. }
  140.  
  141. void
  142. free (void *mem)
  143. {
  144.   struct mem_block *block;
  145.   u_int *end_magic;
  146.  
  147.   /* this seems to be standard... don't like it though ! */
  148.   if (! mem)
  149.     return;
  150.  
  151.   block = (struct mem_block *)((u_char *)mem - offsetof (struct mem_block, realblock));
  152.  
  153.   if (((struct memalign_ptr *)mem - 1)->magic == MEMALIGN_MAGIC)
  154.     {
  155.       block = (struct mem_block *)
  156.           ((u_char *)block - ((struct memalign_ptr *)mem - 1)->alignment);
  157.     }
  158.  
  159.    
  160.  
  161.   if (((u_int)block & 1) ||
  162.       (block->magic[0] != MAGIC1 || block->magic[1] != MAGIC1))
  163.     {
  164.       ix_panic ("free: start of block corrupt!");
  165.       syscall (SYS_exit, 20);
  166.     }
  167.  
  168.   end_magic = (u_int *)((u_char *)&block->realblock + block->size);
  169.   if (end_magic[0] != MAGIC2)
  170.     {
  171.       ix_panic ("free: end of block corrupt!");
  172.       syscall (SYS_exit, 20);
  173.     }
  174.  
  175.   Forbid ();
  176.   Remove ((struct Node *) block);
  177.   Permit ();
  178.  
  179.   mem_used -= block->size;
  180.   b_free(block, block->size + sizeof (struct mem_block));
  181. }
  182.  
  183.  
  184. void all_free (void)
  185. {
  186.   struct mem_block *b, *nb;
  187.   static int errno_dummy;
  188.  
  189.   /* Since errno (= *u.u_errno) is used by sigsetmask, even though all_free
  190.      frees the memory u.u_errno points to, we point it to our own temporary
  191.      errno dummy variable. */
  192.   u.u_errno = &errno_dummy;
  193.  
  194.   /* be sure to use *our* memory lists in here, never all_free() the parents
  195.      list.... */
  196.   
  197.   for (b  = (struct mem_block *) own_mem_list.mlh_Head;
  198.        (nb = b->next);
  199.        b  = nb)
  200.     {
  201.       b_free(b, b->size + sizeof (struct mem_block));
  202.     }
  203.  
  204.   /* this makes it possible to call all_free() more than once */
  205.   NewList ((struct List *) &own_mem_list);
  206. }
  207.  
  208. void *
  209. realloc (void *mem, size_t size)
  210. {
  211.   struct mem_block *block;
  212.   u_int *end_magic;
  213.   void *res;
  214.  
  215.   if (! mem)
  216.     return (void *) malloc (size);
  217.     
  218.   block = (struct mem_block *)((u_char *)mem - offsetof (struct mem_block, realblock));
  219.  
  220.   
  221.   /* duplicate the code in free() here so we don't have to check those magic
  222.    * numbers twice */
  223.   
  224.   if (((struct memalign_ptr *)mem - 1)->magic == MEMALIGN_MAGIC)
  225.     {
  226.       block = (struct mem_block *)
  227.           ((u_char *)block - ((struct memalign_ptr *)mem - 1)->alignment);
  228.     }
  229.  
  230.    
  231.   if (((u_int)block & 1) ||
  232.       (block->magic[0] != MAGIC1 || block->magic[1] != MAGIC1))
  233.     {
  234.       ix_panic ("realloc: start of block corrupt!");
  235.       syscall (SYS_exit, 20);
  236.     }
  237.  
  238.   end_magic = (u_int *)((u_char *)&block->realblock + block->size);
  239.   if (end_magic[0] != MAGIC2)
  240.     {
  241.       ix_panic ("realloc: end of block corrupt!");
  242.       syscall (SYS_exit, 20);
  243.     }
  244.  
  245.   /* now that the block is validated, check whether we have to really
  246.    * realloc, or if we just can return the old block */
  247.   if (block->size >= size)
  248.     res = mem;
  249.   else
  250.     {
  251.       res = (void *) malloc (size);
  252.       if (res)
  253.     {
  254.       Forbid ();
  255.           Remove ((struct Node *) block);
  256.           Permit ();
  257.  
  258.       CopyMemQuick (mem, res, block->size);
  259.  
  260.       /* according to the manpage, the old buffer should only be
  261.        * freed, if the allocation of the new buffer was successful */
  262.       mem_used -= block->size;
  263.       b_free(block, block->size + sizeof (struct mem_block));
  264.     }
  265.     }
  266.  
  267.   return res;
  268. }
  269.